/*
 * Copyright (C) 2010 Graham Allan
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package edu.strath.cis.grallan.findbugs.adaptiveranking.population;

import edu.strath.cis.grallan.findbugs.adaptiveranking.PositiveMatchers;
import edu.strath.cis.grallan.findbugs.adaptiveranking.UserDesignationToPositivesMap.Positive;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.filter.Matcher;

/**
 * A Population is an area of code which contains zero or more bug alerts.
 * 
 * Populations are used to exploit correlations between error reports. Kremenek et al. have shown
 * that true or false positives tend to cluster by their location in the source code. A Population
 * represents a set of alerts which correlate in some way and which can be used to calculate a
 * probability whether a given, new alert is a true or false positive.
 * 
 * Although initially based on alert location, populations can be based on any factor which allows a
 * bug to only belong to one of the population type. For instance, priority or bug rank population.
 * 
 * @see Kremenek et al. "Correlation Exploitation in Error Ranking" {@link http
 *      ://portal.acm.org/ft_gateway.cfm?id=1029909&type=pdf}
 * 
 * @author Graham Allan (grallan@cis.strath.ac.uk)
 */
public interface Population {

	/**
	 * The adjustment factor is a value used to indicate the likelihood an unseen bug alert is a
	 * true or false positive.
	 * 
	 * The adjustment factor is a real number within the range [-1, 1]. A value of -1 indicates that
	 * a given bug alert is fully expected to be a false positive. Similarly, a value of +1
	 * indicates a true positive is expected.
	 * 
	 * The adjustment factor is calculated using the number of alerts which have already been deemed
	 * to be a true or false positive. Given an alert (a), and this Population (p), and previous
	 * alerts being deemed either a true positive (tp) or a false positive (fp) the adjustment
	 * factor AF should be calculated as: AF{p}(a) = (# tp - # fp) / (# tp + # fp).
	 * 
	 * Adjustment factors are described in more detail in S. S. Heckman's Adaptively Ranking Alerts
	 * Generated From Automated Static Analysis.
	 * 
	 * @return double in the range [-1, 1]
	 */
	double adjustmentFactor();

	/**
	 * Adds an alert to this population. Future adjustment factor calculations should include the
	 * added bug alert.
	 * 
	 * Implementing classes may impose restrictions on the alert being added. Invalid additions may
	 * throw a PopulationException or ignore an added bug alert.
	 * 
	 * @param bugInstance
	 * @throws PopulationException
	 *             when the added bug alert is invalid for <code>this</code> population.
	 * @return this Population (to allow method chaining)
	 */
	Population addAlert(BugInstance bugInstance);

	/**
	 * Returns the total number of alerts within <code>this</code> population, regardless of
	 * {@link Positive} value of the
	 * 
	 * @return
	 */
	int size();

	/**
	 * Returns the number of bugs within <code>this</code> population which match.
	 * 
	 * Although any matchers can be used here, some particular matchers which may be of use are: <br>
	 * {@link PositiveMatchers#FALSE_POSITIVE_MATCHER} and
	 * {@link PositiveMatchers#TRUE_POSITIVE_MATCHER}
	 * 
	 * @param bugMatcher
	 *            matcher to compare to the bugs
	 * @return int number of matching bugs
	 */
	int numberOf(Matcher bugMatcher);

	/**
	 * Returns true if it the given bug is valid to add to <code>this</code> population.
	 * 
	 * The relationship of this method is symmetric with {@link #addAlert(BugInstance)} in terms of
	 * exceptions thrown. It is guaranteed that if this method returns <code>true</code>, then
	 * <code>addAlert()</code>, called with the <i>same bug</i> will not throw an exception.
	 * Similarly, if this method returns <code>false</code>, <code>addAlert()</code> is guaranteed
	 * to throw a {@link PopulationException}.
	 * 
	 * 
	 * @param bug
	 * @return
	 */
	boolean isValidAlert(BugInstance bug);

	/**
	 * Returns a String describing this population. Usually this would be an attribute which is
	 * shared by all members of the population.
	 */
	String populationDescriptor();
}
